using System;
using System.Collections.Generic;
using OracleInternal.Common;
using OracleInternal.ServiceObjects;

namespace OracleInternal.TTC.Accessors
{
	internal class TTCBinaryFloatAccessor : Accessor
	{
		internal static int BINARY_FLOAT_MAX_LENGTH = 4;

		internal TTCBinaryFloatAccessor(ColumnDescribeInfo colMetaData, MarshallingEngine marshallingEngine, bool bForBind)
			: base(colMetaData, marshallingEngine, bForBind)
		{
			if (!bForBind)
			{
				InitForDataAccess(m_colMetaData.m_maxLength);
			}
		}

		internal override void InitForDataAccess(int max_len)
		{
			if (max_len > 0 && max_len < m_internalTypeMaxLength)
			{
				m_internalTypeMaxLength = max_len;
			}
			else
			{
				m_internalTypeMaxLength = BINARY_FLOAT_MAX_LENGTH;
			}
			m_byteLength = m_internalTypeMaxLength;
		}

		internal static float GetFloatFromByteArray(byte[] byteVal, int startOffset)
		{
			int num = byteVal[startOffset];
			int num2 = byteVal[startOffset + 1];
			int num3 = byteVal[startOffset + 2];
			int num4 = byteVal[startOffset + 3];
			if (((uint)num & 0x80u) != 0)
			{
				num &= 0x7F;
				num2 &= 0xFF;
				num3 &= 0xFF;
				num4 &= 0xFF;
			}
			else
			{
				num = ~num & 0xFF;
				num2 = ~num2 & 0xFF;
				num3 = ~num3 & 0xFF;
				num4 = ~num4 & 0xFF;
			}
			return BitConverter.ToSingle(BitConverter.GetBytes((num << 24) | (num2 << 16) | (num3 << 8) | num4), 0);
		}

		internal float GetValue(int currentRow)
		{
			float result = 0f;
			int num = m_totalLengthOfData[currentRow];
			if (num > 0)
			{
				List<ArraySegment<byte>> list = m_RowDataSegments[currentRow];
				if (list != null)
				{
					byte[] array = null;
					int startOffset = 0;
					if (list.Count > 1)
					{
						array = new byte[num];
						Accessor.CopyDataToUserBuffer(list, 0, array, 0, num);
					}
					else
					{
						array = list[0].Array;
						startOffset = list[0].Offset;
					}
					result = GetFloatFromByteArray(array, startOffset);
				}
			}
			return result;
		}

		internal float GetValue(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex)
		{
			byte[] byteRep = null;
			return GetValue(dataUnmarshaller, currentRow, columnIndex, out byteRep);
		}

		internal float GetValue(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex, out byte[] byteRep)
		{
			float result = 0f;
			int length = 0;
			byteRep = null;
			try
			{
				dataUnmarshaller.StartAccumulatingColumnData(currentRow, columnIndex, m_colDataSegments);
				dataUnmarshaller.UnmarshalCLR_ScanOnly(m_colMetaData.m_maxLength, ref length);
				if (length > 0)
				{
					int startOffset = 0;
					byteRep = new byte[length];
					Accessor.CopyDataToUserBuffer(m_colDataSegments, 0, byteRep, 0, length);
					return GetFloatFromByteArray(byteRep, startOffset);
				}
				return result;
			}
			finally
			{
				m_colDataSegments.Clear();
				dataUnmarshaller.m_bAccumulateByteSegments = false;
				dataUnmarshaller.m_dataSegments = null;
			}
		}

		internal override float GetFloat(int currentRow)
		{
			return GetValue(currentRow);
		}

		internal override float GetFloat(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex, out byte[] byteRep)
		{
			return GetValue(dataUnmarshaller, currentRow, columnIndex, out byteRep);
		}

		internal override float GetFloat(DataUnmarshaller dataUnmarshaller, int currentRow, int columnIndex)
		{
			return GetValue(dataUnmarshaller, currentRow, columnIndex);
		}

		public static byte[] FloatToCanonicalFormatBytes(float f)
		{
			if (f == 0f)
			{
				f = 0f;
			}
			int num = BitConverter.ToInt32(BitConverter.GetBytes(f), 0);
			byte[] array = new byte[4];
			int num2 = num;
			int num4;
			int num3;
			int num5 = (num4 = (num3 = num >> 8) >> 8) >> 8;
			if ((num5 & 0x80) == 0)
			{
				num5 |= 0x80;
			}
			else
			{
				num5 = ~num5;
				num4 = ~num4;
				num3 = ~num3;
				num2 = ~num2;
			}
			array[3] = (byte)num2;
			array[2] = (byte)num3;
			array[1] = (byte)num4;
			array[0] = (byte)num5;
			return array;
		}
	}
}
